package com.lovegu.netty.client;

import com.lovegu.netty.coder.NettyKryoDecoder;
import com.lovegu.netty.coder.NettyKryoEncoder;
import com.lovegu.netty.res.RpcRequest;
import com.lovegu.netty.res.RpcResponse;
import com.lovegu.netty.serialize.KryoSerializer;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.util.AttributeKey;

/**
 * @author 老顾 1437594522@qq.com
 * @description
 * @date 2022/11/22 21:06
 */
public class NettyClient {

    //地址
    private final String host;
    //端口号
    private final int port;
    private static Bootstrap b;

    /**
     * 构造方法
     * @param host
     * @param port
     */
    public NettyClient(String host, int port) {
        this.host = host;
        this.port = port;
    }

    //初始化相关资源，如 EventLoopGroup,Bootstrap
    static {
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();
        b = new Bootstrap();
        KryoSerializer kryoSerializer = new KryoSerializer();
        b.group(eventLoopGroup)
                .channel(NioSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.INFO))
                // 连接的超时时间，超过这个时间还是建立不上的话，则代表连接失败
                // 如果15秒内没有发送数据给服务端的话，久发送一次心跳请求
                .option(ChannelOption.CONNECT_TIMEOUT_MILLIS,5000)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {
                        //自定义序列合编码解码器 RpcResponse -> ByteBuf
                        socketChannel.pipeline().addLast(new NettyKryoDecoder(kryoSerializer, RpcResponse.class));
                        //ByteBuf -> RpcRequest
                        socketChannel.pipeline().addLast(new NettyKryoEncoder(kryoSerializer, RpcRequest.class));
                        socketChannel.pipeline().addLast(new NettyClientHandler());
                    }
                });
    }
    public RpcResponse sendMessage(RpcRequest rpcRequest) {
        try {
            ChannelFuture f = b.connect(host, port).sync();
            System.out.println("客户端地址："+host+":"+port);
            Channel futureChannel = f.channel();
            System.out.println("发送消息");
            if (futureChannel != null){
                futureChannel.writeAndFlush(rpcRequest).addListener(future -> {
                   if (future.isSuccess()) {
                       System.out.println("客户端发送消息："+rpcRequest.toString());
                   }else {
                       System.out.println("发送失败："+future.cause().toString());
                   }
                });
                //阻塞等待，直到Channel关闭
                futureChannel.closeFuture().sync();
                //将服务端返回的数据也就是RpcResponse对象取出
                AttributeKey<RpcResponse> key = AttributeKey.valueOf("rpcResponse");
                return futureChannel.attr(key).get();
            }
        }catch (InterruptedException e){
            System.out.println("连接服务端导致的异常："+e);
        }
        return null;
    }

    public static void main(String[] args) {
        RpcRequest rpcRequest = RpcRequest.builder()
                .interfaceName("interface")
                .methodName("hello").build();
        NettyClient nettyClient = new NettyClient("127.0.0.1", 9090);
        for (int i = 0; i < 3; i++) {
            nettyClient.sendMessage(rpcRequest);
        }
        RpcResponse rpcResponse = nettyClient.sendMessage(rpcRequest);
        System.out.println(rpcResponse.toString());
    }
}
